//编译列表元素
//后用逗号分割成字符串
function genNodeList(nodes, context) {
    const { push } = context;
    for (let i = 0; i < nodes.length; i++) {
        const node = nodes[i];
        genNode(node, context);
        if (i < nodes.length - 1) {
            push(",");
        }
    }
}
//编译数组
function genArrayExpression(node, context) {
    const { push } = context;
    push("[");
    genNodeList(node.elements, context);
    push("]");
}

//编译成函数
function genFunctionDecl(node, context) {
    const { push, indent, deIndent } = context;
    push(`function ${node.id.name}`);
    push("(");
    //调用geNodeList为函数的参数生成代码
    genNodeList(node.params, context);
    push(")");
    push("{");
    //缩进
    indent();
    //函数体生成代码，这里递归地调用了genNode函数
    node.body.forEach((n) => genNode(n, context));
    //取消缩进
    deIndent();
    push("}");
}

//编译返回语句
function genReturnStatement(node, context) {
    const { push } = context;
    push("return ");
    //调用genNOde函数递归的生成放回代码
    genNode(node.return, context);
}
//编译字符串
function genStringLiteral(node, context) {
    const { push } = context;
    push(`'${node.value}'`);
}
//回调函数h
function genCallExpression(node, context) {
    const { push } = context;
    //取得函数名称和参数列表
    const { callee, arguments: args } = node;
    //生成函数调用代码
    push(`${callee.name}(`);
    //调用genNodeList生成参数代码
    genNodeList(args, context);
    //补全括号
    push(")");
}
//根据节点类型的不一样，分发处理函数
function genNode(node, context) {
    switch (node.type) {
        case "FunctionDecl":
            genFunctionDecl(node, context);
            break;
        case "ReturnStatement":
            genReturnStatement(node, context);
            break;
        case "CallExpression":
            genCallExpression(node, context);
            break;
        case "StringLiteral":
            genStringLiteral(node, context);
            break;
        case "ArrayExpression":
            genArrayExpression(node, context);
            break;
    }
}

function generate(node) {
    //创建一个上下文
    const context = {
        //存储组中生成的渲染函数代码
        code: "",
        //在生成代码是，通过调用push函数生成代码的拼接
        push(code) {
            context.code += code;
        },
        //当前缩进的级别，初始值为0，即没有缩进
        currentIndent: 0,
        /**
         * 该函数用来换行，即在代码后面最追加\n
         * 另外，换行的时候应该保留缩进，搜易我们还要追加currentIndent*2个空格字符
         */
        newline() {
            context.code += "\n" + ` `.repeat(context.currentIndent);
        },
        //用来缩进，即让currentIndent自增后，调用换行函数
        indent() {
            context.currentIndent++;
            context.newline();
        },
        //取消缩进,即让currentIndent自减，再调用换行函数
        deIndent() {
            context.currentIndent--;
            context.newline();
        },
    };

    //调用genNode函数完成代码生成的工作
    genNode(node, context);
    //放回渲染函数代码
    return context.code;
}